﻿using FreeRedis.Internal;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace FreeRedis
{
	public interface IRedisClient
	{
		List<Func<IInterceptor>> Interceptors { get; }

		event EventHandler<ConnectedEventArgs> Connected;
		event EventHandler<NoticeEventArgs> Notice;
		event EventHandler<UnavailableEventArgs> Unavailable;

		RedisClient.PipelineHook StartPipe();
		RedisClient.DatabaseHook GetDatabase(int? index = null);
		RedisClient.TransactionHook Multi();
		void Auth(string password);
		void Auth(string username, string password);
		void ClientCaching(Confirm confirm);
		string ClientGetName();
		long ClientGetRedir();
		long ClientId();
		void ClientKill(string ipport);
		long ClientKill(string ipport, long? clientid, ClientType? type, string username, string addr, Confirm? skipme);
		string ClientList(ClientType? type = null);
		void ClientPause(long timeoutMilliseconds);
		void ClientReply(ClientReplyType type);
		void ClientSetName(string connectionName);
		void ClientTracking(bool on_off, long? redirect, string[] prefix, bool bcast, bool optin, bool optout, bool noloop);
		bool ClientUnBlock(long clientid, ClientUnBlockType? type = null);
		string Echo(string message);
		Dictionary<string, object> Hello(string protover, string username = null, string password = null, string clientname = null);
		string Ping(string message = null);
		void Quit();
		void Select(int index);
		long GeoAdd(string key, params GeoMember[] members);
		decimal? GeoDist(string key, string member1, string member2, GeoUnit unit = GeoUnit.m);
		string GeoHash(string key, string member);
		string[] GeoHash(string key, string[] members);
		GeoMember GeoPos(string key, string member);
		GeoMember[] GeoPos(string key, string[] members);
		GeoRadiusResult[] GeoRadius(string key, decimal longitude, decimal latitude, decimal radius, GeoUnit unit = GeoUnit.m, bool withdoord = false, bool withdist = false, bool withhash = false, long? count = null, Collation? collation = null);
		long GeoRadiusStore(string key, decimal longitude, decimal latitude, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, Collation? collation = null, string storekey = null, string storedistkey = null);
		GeoRadiusResult[] GeoRadiusByMember(string key, string member, decimal radius, GeoUnit unit = GeoUnit.m, bool withdoord = false, bool withdist = false, bool withhash = false, long? count = null, Collation? collation = null);
		long GeoRadiusByMemberStore(string key, string member, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, Collation? collation = null, string storekey = null, string storedistkey = null);
		long HDel(string key, params string[] fields);
		bool HExists(string key, string field);
		string HGet(string key, string field);
		T HGet<T>(string key, string field);
		Dictionary<string, string> HGetAll(string key);
		Dictionary<string, T> HGetAll<T>(string key);
		long HIncrBy(string key, string field, long increment);
		decimal HIncrByFloat(string key, string field, decimal increment);
		string[] HKeys(string key);
		long HLen(string key);
		string[] HMGet(string key, params string[] fields);
		T[] HMGet<T>(string key, params string[] fields);
		void HMSet<T>(string key, string field, T value, params object[] fieldValues);
		void HMSet<T>(string key, Dictionary<string, T> keyValues);
		ScanResult<KeyValuePair<string, string>> HScan(string key, long cursor, string pattern, long count);
		ScanResult<KeyValuePair<string, T>> HScan<T>(string key, long cursor, string pattern, long count);
		IEnumerable<KeyValuePair<string, string>[]> HScan(string key, string pattern, long count);
		IEnumerable<KeyValuePair<string, T>[]> HScan<T>(string key, string pattern, long count);
		long HSet<T>(string key, string field, T value, params object[] fieldValues);
		long HSet<T>(string key, Dictionary<string, T> keyValues);
		bool HSetNx<T>(string key, string field, T value);
		long HStrLen(string key, string field);
		string[] HVals(string key);
		T[] HVals<T>(string key);
		bool PfAdd(string key, params object[] elements);
		long PfCount(params string[] keys);
		void PfMerge(string destkey, params string[] sourcekeys);
		long Del(params string[] keys);
		Byte[] Dump(string key);
		bool Exists(string key);
		long Exists(string[] keys);
		bool Expire(string key, int seconds);
		bool Expire(string key, TimeSpan expire);
		bool ExpireAt(string key, DateTime timestamp);
		string[] Keys(string pattern);
		void Migrate(string host, int port, string key, int destinationDb, long timeoutMilliseconds, bool copy, bool replace, string authPassword, string auth2Username, string auth2Password, string[] keys);
		bool Move(string key, int db);
		long? ObjectRefCount(string key);
		long ObjectIdleTime(string key);
		string ObjectEncoding(string key);
		long? ObjectFreq(string key);
		bool Persist(string key);
		bool PExpire(string key, int milliseconds);
		bool PExpireAt(string key, DateTime timestamp);
		long PTtl(string key);
		string RandomKey();
		void Rename(string key, string newkey);
		bool RenameNx(string key, string newkey);
		void Restore(string key, Byte[] serializedValue);
		void Restore(string key, int ttl, Byte[] serializedValue, bool replace = false, bool absTtl = false, int? idleTimeSeconds = null, decimal? frequency = null);
		ScanResult<string> Scan(long cursor, string pattern, long count, string type);
		IEnumerable<string[]> Scan(string pattern, long count, string type);
		string[] Sort(string key, string byPattern = null, long offset = 0, long count = 0, string[] getPatterns = null, Collation? collation = null, bool alpha = false);
		long SortStore(string storeDestination, string key, string byPattern = null, long offset = 0, long count = 0, string[] getPatterns = null, Collation? collation = null, bool alpha = false);
		long Touch(params string[] keys);
		long Ttl(string key);
		KeyType Type(string key);
		long UnLink(params string[] keys);
		long Wait(long numreplicas, long timeoutMilliseconds);
		string BLPop(string key, int timeoutSeconds);
		T BLPop<T>(string key, int timeoutSeconds);
		KeyValue<string> BLPop(string[] keys, int timeoutSeconds);
		KeyValue<T> BLPop<T>(string[] keys, int timeoutSeconds);
		string BRPop(string key, int timeoutSeconds);
		T BRPop<T>(string key, int timeoutSeconds);
		KeyValue<string> BRPop(string[] keys, int timeoutSeconds);
		KeyValue<T> BRPop<T>(string[] keys, int timeoutSeconds);
		string BRPopLPush(string source, string destination, int timeoutSeconds);
		T BRPopLPush<T>(string source, string destination, int timeoutSeconds);
		string LIndex(string key, long index);
		T LIndex<T>(string key, long index);
		long LInsert(string key, InsertDirection direction, object pivot, object element);
		long LLen(string key);
		string LPop(string key);
		T LPop<T>(string key);
		long LPos<T>(string key, T element, int rank = 0);
		long[] LPos<T>(string key, T element, int rank, int count, int maxLen);
		long LPush(string key, params object[] elements);
		long LPushX(string key, params object[] elements);
		string[] LRange(string key, long start, long stop);
		T[] LRange<T>(string key, long start, long stop);
		long LRem<T>(string key, long count, T element);
		void LSet<T>(string key, long index, T element);
		void LTrim(string key, long start, long stop);
		string RPop(string key);
		T RPop<T>(string key);
		string RPopLPush(string source, string destination);
		T RPopLPush<T>(string source, string destination);
		long RPush(string key, params object[] elements);
		long RPushX(string key, params object[] elements);
		string BfReserve(string key, decimal errorRate, long capacity, int expansion = 2, bool nonScaling = false);
		bool BfAdd(string key, string item);
		bool[] BfMAdd(string key, string[] items);
		string BfInsert(string key, string[] items, long? capacity = null, string error = null, int expansion = 2, bool noCreate = false, bool nonScaling = false);
		bool BfExists(string key, string item);
		bool[] BfMExists(string key, string[] items);
		ScanResult<Byte[]> BfScanDump(string key, long iter);
		string BfLoadChunk(string key, long iter, Byte[] data);
		Dictionary<string, string> BfInfo(string key);
		RedisClient.LockController Lock(string name, int timeoutSeconds, bool autoDelay = true);
		string CmsInitByDim(string key, long width, long depth);
		string CmsInitByProb(string key, decimal error, decimal probability);
		long CmsIncrBy(string key, string item, long increment);
		long[] CmsIncrBy(string key, Dictionary<string, long> itemIncrements);
		long[] CmsQuery(string key, string[] items);
		string CmsMerge(string dest, long numKeys, string[] src, long[] weights);
		Dictionary<string, string> CmsInfo(string key);
		string CfReserve(string key, long capacity, long? bucketSize = null, long? maxIterations = null, int? expansion = null);
		bool CfAdd(string key, string item);
		bool CfAddNx(string key, string item);
		string CfInsert(string key, string[] items, long? capacity = null, bool noCreate = false);
		string CfInsertNx(string key, string[] items, long? capacity = null, bool noCreate = false);
		bool CfExists(string key, string item);
		bool CfDel(string key, string item);
		long CfCount(string key, string item);
		ScanResult<Byte[]> CfScanDump(string key, long iter);
		string CfLoadChunk(string key, long iter, Byte[] data);
		Dictionary<string, string> CfInfo(string key);
		string TopkReserve(string key, long topk, long width, long depth, decimal decay);
		string[] TopkAdd(string key, string[] items);
		string TopkIncrBy(string key, string item, long increment);
		string[] TopkIncrBy(string key, Dictionary<string, long> itemIncrements);
		bool[] TopkQuery(string key, string[] items);
		long[] TopkCount(string key, string[] items);
		string[] TopkList(string key);
		Dictionary<string, string> TopkInfo(string key);
		string JsonGet(string key, string indent = null, string newline = null, string space = null, params string[] paths);
		string[] JsonMGet(string[] keys, string path = "$");
		void JsonSet(string key, string value, string path = "$", bool nx = false, bool xx = false);
		void JsonMSet(string[] keys, string[] values, string[] paths);
		void JsonMerge(string key, string path, string value);
		long JsonDel(string key, string path = "$");
		long[] JsonArrInsert(string key, string path, long index = 0, params object[] values);
		long[] JsonArrAppend(string key, string path, params object[] values);
		long[] JsonArrIndex<T>(string key, string path, T value) where T : struct;
		long[] JsonArrLen(string key, string path);
		object[] JsonArrPop(string key, string path, int index = -1);
		long[] JsonArrTrim(string key, string path, int start, int stop);
		long JsonClear(string key, string path = "$");
		long[] JsonDebugMemory(string key, string path = "$");
		long JsonForget(string key, string path = "$");
		string JsonNumIncrBy(string key, string path, double value);
		string JsonNumMultBy(string key, string path, double value);
		string[][] JsonObjKeys(string key, string path = "$");
		long[] JsonObjLen(string key, string path = "$");
		object[][] JsonResp(string key, string path = "$");
		long[] JsonStrAppend(string key, string value, string path = "$");
		long[] JsonStrLen(string key, string path = "$");
		bool[] JsonToggle(string key, string path = "$");
		string[] JsonType(string key, string path = "$");
		SubscribeListObject SubscribeList(string listKey, Action<string> onMessage);
		SubscribeListObject SubscribeList(string[] listKeys, Action<string, string> onMessage);
		SubscribeListBroadcastObject SubscribeListBroadcast(string listKey, string clientId, Action<string> onMessage);
		SubscribeStreamObject SubscribeStream(string streamKey, Action<Dictionary<string, string>> onMessage);
		long Publish(string channel, string message);
		long Publish(string channel, Byte[] message);
		string[] PubSubChannels(string pattern = "*");
		long PubSubNumSub(string channel);
		long[] PubSubNumSub(string[] channels);
		long PubSubNumPat();
		void PUnSubscribe(params string[] pattern);
		void UnSubscribe(params string[] channels);
		bool ScriptExists(string sha1);
		bool[] ScriptExists(string[] sha1);
		void ScriptFlush();
		void ScriptKill();
		string ScriptLoad(string script);
		string[] AclCat(string categoryname = null);
		long AclDelUser(params string[] username);
		string AclGenPass(int bits = 0);
		AclGetUserResult AclGetUser(string username = "default");
		string[] AclList();
		void AclLoad();
		LogResult[] AclLog(long count = 0);
		void AclSave();
		void AclSetUser(string username, params string[] rule);
		string[] AclUsers();
		string AclWhoami();
		string BgRewriteAof();
		string BgSave(string schedule = null);
		object[] Command();
		long CommandCount();
		string[] CommandGetKeys(params string[] command);
		object[] CommandInfo(params string[] command);
		Dictionary<string, string> ConfigGet(string parameter);
		void ConfigResetStat();
		void ConfigRewrite();
		void ConfigSet<T>(string parameter, T value);
		long DbSize();
		string DebugObject(string key);
		void FlushAll(bool isasync = false);
		void FlushDb(bool isasync = false);
		string Info(string section = null);
		DateTime LastSave();
		string LatencyDoctor();
		string MemoryDoctor();
		string MemoryMallocStats();
		void MemoryPurge();
		Dictionary<string, object> MemoryStats();
		long MemoryUsage(string key, long count = 0);
		void ReplicaOf(string host, int port);
		RoleResult Role();
		void Save();
		void SlaveOf(string host, int port);
		void SwapDb(int index1, int index2);
		DateTime Time();
		long SAdd(string key, params object[] members);
		long SCard(string key);
		string[] SDiff(params string[] keys);
		T[] SDiff<T>(params string[] keys);
		long SDiffStore(string destination, params string[] keys);
		string[] SInter(params string[] keys);
		T[] SInter<T>(params string[] keys);
		long SInterStore(string destination, params string[] keys);
		bool SIsMember<T>(string key, T member);
		string[] SMembers(string key);
		T[] SMembers<T>(string key);
		bool[] SMIsMember(string key, params object[] members);
		bool SMove<T>(string source, string destination, T member);
		string SPop(string key);
		T SPop<T>(string key);
		string[] SPop(string key, int count);
		T[] SPop<T>(string key, int count);
		string SRandMember(string key);
		T SRandMember<T>(string key);
		string[] SRandMember(string key, int count);
		T[] SRandMember<T>(string key, int count);
		long SRem(string key, params object[] members);
		ScanResult<string> SScan(string key, long cursor, string pattern, long count);
		ScanResult<T> SScan<T>(string key, long cursor, string pattern, long count);
		IEnumerable<string[]> SScan(string key, string pattern, long count);
		IEnumerable<T[]> SScan<T>(string key, string pattern, long count);
		string[] SUnion(params string[] keys);
		T[] SUnion<T>(params string[] keys);
		long SUnionStore(string destination, params string[] keys);
		ZMember BZPopMin(string key, int timeoutSeconds);
		KeyValue<ZMember> BZPopMin(string[] keys, int timeoutSeconds);
		ZMember BZPopMax(string key, int timeoutSeconds);
		KeyValue<ZMember> BZPopMax(string[] keys, int timeoutSeconds);
		long ZAdd(string key, decimal score, string member, params object[] scoreMembers);
		long ZAdd(string key, ZMember[] scoreMembers, ZAddThan? than = null, bool ch = false);
		long ZAddNx(string key, decimal score, string member, params object[] scoreMembers);
		long ZAddNx(string key, ZMember[] scoreMembers, ZAddThan? than = null, bool ch = false);
		long ZAddXx(string key, decimal score, string member, params object[] scoreMembers);
		long ZAddXx(string key, ZMember[] scoreMembers, ZAddThan? than = null, bool ch = false);
		long ZCard(string key);
		long ZCount(string key, decimal min, decimal max);
		long ZCount(string key, string min, string max);
		decimal ZIncrBy(string key, decimal increment, string member);
		long ZInterStore(string destination, string[] keys, int[] weights = null, ZAggregate? aggregate = null);
		long ZLexCount(string key, string min, string max);
		ZMember ZPopMin(string key);
		ZMember[] ZPopMin(string key, int count);
		ZMember ZPopMax(string key);
		ZMember[] ZPopMax(string key, int count);
		string[] ZRange(string key, decimal start, decimal stop);
		ZMember[] ZRangeWithScores(string key, decimal start, decimal stop);
		string[] ZRangeByLex(string key, string min, string max, int offset = 0, int count = 0);
		string[] ZRangeByScore(string key, decimal min, decimal max, int offset = 0, int count = 0);
		string[] ZRangeByScore(string key, string min, string max, int offset = 0, int count = 0);
		ZMember[] ZRangeByScoreWithScores(string key, decimal min, decimal max, int offset = 0, int count = 0);
		ZMember[] ZRangeByScoreWithScores(string key, string min, string max, int offset = 0, int count = 0);
		long? ZRank(string key, string member);
		long ZRem(string key, params string[] members);
		long ZRemRangeByLex(string key, string min, string max);
		long ZRemRangeByRank(string key, long start, long stop);
		long ZRemRangeByScore(string key, decimal min, decimal max);
		long ZRemRangeByScore(string key, string min, string max);
		string[] ZRevRange(string key, decimal start, decimal stop);
		ZMember[] ZRevRangeWithScores(string key, decimal start, decimal stop);
		string[] ZRevRangeByLex(string key, decimal max, decimal min, int offset = 0, int count = 0);
		string[] ZRevRangeByLex(string key, string max, string min, int offset = 0, int count = 0);
		string[] ZRevRangeByScore(string key, decimal max, decimal min, int offset = 0, int count = 0);
		string[] ZRevRangeByScore(string key, string max, string min, int offset = 0, int count = 0);
		ZMember[] ZRevRangeByScoreWithScores(string key, decimal max, decimal min, int offset = 0, int count = 0);
		ZMember[] ZRevRangeByScoreWithScores(string key, string max, string min, int offset = 0, int count = 0);
		long ZRevRank(string key, string member);
		decimal? ZScore(string key, string member);
		long ZUnionStore(string destination, string[] keys, int[] weights = null, ZAggregate? aggregate = null);
		string[] ZRandMember(string key, int count, bool repetition);
		ZMember[] ZRandMemberWithScores(string key, int count, bool repetition);
		ScanResult<ZMember> ZScan(string key, long cursor, string pattern, long count = 0);
		IEnumerable<ZMember[]> ZScan(string key, string pattern, long count);
		long XAck(string key, string group, params string[] id);
		string XAdd<T>(string key, string field, T value, params object[] fieldValues);
		string XAdd<T>(string key, long maxlen, string id, string field, T value, params object[] fieldValues);
		string XAdd<T>(string key, Dictionary<string, T> fieldValues);
		string XAdd<T>(string key, long maxlen, string id, Dictionary<string, T> fieldValues);
		StreamsXAutoClaimResult XAutoClaim(string key, string group, string consumer, long minIdleTime, string start, long count = 0);
		StreamsEntry[] XClaim(string key, string group, string consumer, long minIdleTime, params string[] id);
		StreamsEntry[] XClaim(string key, string group, string consumer, long minIdleTime, string[] id, long idle, long retryCount, bool force);
		string[] XClaimJustId(string key, string group, string consumer, long minIdleTime, params string[] id);
		string[] XClaimJustId(string key, string group, string consumer, long minIdleTime, string[] id, long idle, long retryCount, bool force);
		long XDel(string key, params string[] id);
		void XGroupCreate(string key, string group, string id = "$", bool MkStream = false);
		void XGroupSetId(string key, string group, string id = "$");
		bool XGroupDestroy(string key, string group);
		void XGroupCreateConsumer(string key, string group, string consumer);
		long XGroupDelConsumer(string key, string group, string consumer);
		StreamsXInfoStreamResult XInfoStream(string key);
		StreamsXInfoStreamFullResult XInfoStreamFull(string key, long count = 10);
		StreamsXInfoGroupsResult[] XInfoGroups(string key);
		StreamsXInfoConsumersResult[] XInfoConsumers(string key, string group);
		long XLen(string key);
		StreamsXPendingResult XPending(string key, string group);
		StreamsXPendingConsumerResult[] XPending(string key, string group, string start, string end, long count, string consumer = null);
		StreamsEntry[] XRange(string key, string start, string end, long count = -1);
		StreamsEntry[] XRevRange(string key, string end, string start, long count = -1);
		StreamsEntry XRead(long block, string key, string id);
		StreamsEntryResult[] XRead(long count, long block, string key, string id, params string[] keyIds);
		StreamsEntryResult[] XRead(long count, long block, Dictionary<string, string> keyIds);
		StreamsEntry XReadGroup(string group, string consumer, long block, string key, string id);
		StreamsEntryResult[] XReadGroup(string group, string consumer, long count, long block, bool noack, string key, string id, params string[] keyIds);
		StreamsEntryResult[] XReadGroup(string group, string consumer, long count, long block, bool noack, Dictionary<string, string> keyIds);
		long XTrim(string key, long count);
		long Append<T>(string key, T value);
		long BitCount(string key, long start, long end);
        long[] BitField(string key, params BitFieldAction[] actions);
        long BitOp(BitOpOperation operation, string destkey, params string[] keys);
		long BitPos(string key, bool bit, long? start = null, long? end = null);
		long Decr(string key);
		long DecrBy(string key, long decrement);
		string Get(string key);
		T Get<T>(string key);
		void Get(string key, Stream destination, int bufferSize = 1024);
		bool GetBit(string key, long offset);
		string GetRange(string key, long start, long end);
		T GetRange<T>(string key, long start, long end);
		string GetSet<T>(string key, T value);
		long Incr(string key);
		long IncrBy(string key, long increment);
		decimal IncrByFloat(string key, decimal increment);
		string[] MGet(params string[] keys);
		T[] MGet<T>(params string[] keys);
		void MSet(string key, object value, params object[] keyValues);
		void MSet<T>(Dictionary<string, T> keyValues);
		bool MSetNx(string key, object value, params object[] keyValues);
		bool MSetNx<T>(Dictionary<string, T> keyValues);
		void PSetEx<T>(string key, long milliseconds, T value);
		void Set<T>(string key, T value, int timeoutSeconds = 0);
		void Set<T>(string key, T value, TimeSpan timeout);
		void Set<T>(string key, T value, bool keepTtl);
		bool SetNx<T>(string key, T value, int timeoutSeconds);
		bool SetNx<T>(string key, T value, TimeSpan timeout);
		bool SetXx<T>(string key, T value, int timeoutSeconds = 0);
		bool SetXx<T>(string key, T value, TimeSpan timeout);
		bool SetXx<T>(string key, T value, bool keepTtl);
		string Set<T>(string key, T value, TimeSpan timeout, bool keepTtl, bool nx, bool xx, bool get);
		long SetBit(string key, long offset, bool value);
		void SetEx<T>(string key, int seconds, T value);
		bool SetNx<T>(string key, T value);
		long SetRange<T>(string key, long offset, T value);
		long StrLen(string key);
		object Call(CommandPacket cmd);

#if isasync
		Task<object> CallAsync(CommandPacket cmd);
		Task<long> GeoAddAsync(string key, params GeoMember[] members);
		Task<decimal?> GeoDistAsync(string key, string member1, string member2, GeoUnit unit = GeoUnit.m);
		Task<string> GeoHashAsync(string key, string member);
		Task<string[]> GeoHashAsync(string key, string[] members);
		Task<GeoMember> GeoPosAsync(string key, string member);
		Task<GeoMember[]> GeoPosAsync(string key, string[] members);
		Task<GeoRadiusResult[]> GeoRadiusAsync(string key, decimal longitude, decimal latitude, decimal radius, GeoUnit unit = GeoUnit.m, bool withdoord = false, bool withdist = false, bool withhash = false, long? count = null, Collation? collation = null);
		Task<long> GeoRadiusStoreAsync(string key, decimal longitude, decimal latitude, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, Collation? collation = null, string storekey = null, string storedistkey = null);
		Task<GeoRadiusResult[]> GeoRadiusByMemberAsync(string key, string member, decimal radius, GeoUnit unit = GeoUnit.m, bool withdoord = false, bool withdist = false, bool withhash = false, long? count = null, Collation? collation = null);
		Task<long> GeoRadiusByMemberStoreAsync(string key, string member, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, Collation? collation = null, string storekey = null, string storedistkey = null);
		Task<long> HDelAsync(string key, params string[] fields);
		Task<bool> HExistsAsync(string key, string field);
		Task<string> HGetAsync(string key, string field);
		Task<T> HGetAsync<T>(string key, string field);
		Task<Dictionary<string, string>> HGetAllAsync(string key);
		Task<Dictionary<string, T>> HGetAllAsync<T>(string key);
		Task<long> HIncrByAsync(string key, string field, long increment);
		Task<decimal> HIncrByFloatAsync(string key, string field, decimal increment);
		Task<string[]> HKeysAsync(string key);
		Task<long> HLenAsync(string key);
		Task<string[]> HMGetAsync(string key, params string[] fields);
		Task<T[]> HMGetAsync<T>(string key, params string[] fields);
		Task HMSetAsync<T>(string key, string field, T value, params object[] fieldValues);
		Task HMSetAsync<T>(string key, Dictionary<string, T> keyValues);
		Task<ScanResult<KeyValuePair<string, string>>> HScanAsync(string key, long cursor, string pattern, long count);
		Task<ScanResult<KeyValuePair<string, T>>> HScanAsync<T>(string key, long cursor, string pattern, long count);
		Task<long> HSetAsync<T>(string key, string field, T value, params object[] fieldValues);
		Task<long> HSetAsync<T>(string key, Dictionary<string, T> keyValues);
		Task<bool> HSetNxAsync<T>(string key, string field, T value);
		Task<long> HStrLenAsync(string key, string field);
		Task<string[]> HValsAsync(string key);
		Task<T[]> HValsAsync<T>(string key);
		Task<bool> PfAddAsync(string key, params object[] elements);
		Task<long> PfCountAsync(params string[] keys);
		Task PfMergeAsync(string destkey, params string[] sourcekeys);
		Task<long> DelAsync(params string[] keys);
		Task<Byte[]> DumpAsync(string key);
		Task<bool> ExistsAsync(string key);
		Task<long> ExistsAsync(string[] keys);
		Task<bool> ExpireAsync(string key, int seconds);
		Task<bool> ExpireAsync(string key, TimeSpan expire);
		Task<bool> ExpireAtAsync(string key, DateTime timestamp);
		Task<string[]> KeysAsync(string pattern);
		Task MigrateAsync(string host, int port, string key, int destinationDb, long timeoutMilliseconds, bool copy, bool replace, string authPassword, string auth2Username, string auth2Password, string[] keys);
		Task<bool> MoveAsync(string key, int db);
		Task<long?> ObjectRefCountAsync(string key);
		Task<long> ObjectIdleTimeAsync(string key);
		Task<string> ObjectEncodingAsync(string key);
		Task<long?> ObjectFreqAsync(string key);
		Task<bool> PersistAsync(string key);
		Task<bool> PExpireAsync(string key, int milliseconds);
		Task<bool> PExpireAtAsync(string key, DateTime timestamp);
		Task<long> PTtlAsync(string key);
		Task<string> RandomKeyAsync();
		Task RenameAsync(string key, string newkey);
		Task<bool> RenameNxAsync(string key, string newkey);
		Task RestoreAsync(string key, Byte[] serializedValue);
		Task RestoreAsync(string key, int ttl, Byte[] serializedValue, bool replace = false, bool absTtl = false, int? idleTimeSeconds = null, decimal? frequency = null);
		Task<ScanResult<string>> ScanAsync(long cursor, string pattern, long count, string type);
		Task<string[]> SortAsync(string key, string byPattern = null, long offset = 0, long count = 0, string[] getPatterns = null, Collation? collation = null, bool alpha = false);
		Task<long> SortStoreAsync(string storeDestination, string key, string byPattern = null, long offset = 0, long count = 0, string[] getPatterns = null, Collation? collation = null, bool alpha = false);
		Task<long> TouchAsync(params string[] keys);
		Task<long> TtlAsync(string key);
		Task<KeyType> TypeAsync(string key);
		Task<long> UnLinkAsync(params string[] keys);
		Task<long> WaitAsync(long numreplicas, long timeoutMilliseconds);
		Task<string> BLPopAsync(string key, int timeoutSeconds);
		Task<T> BLPopAsync<T>(string key, int timeoutSeconds);
		Task<KeyValue<string>> BLPopAsync(string[] keys, int timeoutSeconds);
		Task<KeyValue<T>> BLPopAsync<T>(string[] keys, int timeoutSeconds);
		Task<string> BRPopAsync(string key, int timeoutSeconds);
		Task<T> BRPopAsync<T>(string key, int timeoutSeconds);
		Task<KeyValue<string>> BRPopAsync(string[] keys, int timeoutSeconds);
		Task<KeyValue<T>> BRPopAsync<T>(string[] keys, int timeoutSeconds);
		Task<string> BRPopLPushAsync(string source, string destination, int timeoutSeconds);
		Task<T> BRPopLPushAsync<T>(string source, string destination, int timeoutSeconds);
		Task<string> LIndexAsync(string key, long index);
		Task<T> LIndexAsync<T>(string key, long index);
		Task<long> LInsertAsync(string key, InsertDirection direction, object pivot, object element);
		Task<long> LLenAsync(string key);
		Task<string> LPopAsync(string key);
		Task<T> LPopAsync<T>(string key);
		Task<long> LPosAsync<T>(string key, T element, int rank = 0);
		Task<long[]> LPosAsync<T>(string key, T element, int rank, int count, int maxLen);
		Task<long> LPushAsync(string key, params object[] elements);
		Task<long> LPushXAsync(string key, params object[] elements);
		Task<string[]> LRangeAsync(string key, long start, long stop);
		Task<T[]> LRangeAsync<T>(string key, long start, long stop);
		Task<long> LRemAsync<T>(string key, long count, T element);
		Task LSetAsync<T>(string key, long index, T element);
		Task LTrimAsync(string key, long start, long stop);
		Task<string> RPopAsync(string key);
		Task<T> RPopAsync<T>(string key);
		Task<string> RPopLPushAsync(string source, string destination);
		Task<T> RPopLPushAsync<T>(string source, string destination);
		Task<long> RPushAsync(string key, params object[] elements);
		Task<long> RPushXAsync(string key, params object[] elements);
		Task<string> BfReserveAsync(string key, decimal errorRate, long capacity, int expansion = 2, bool nonScaling = false);
		Task<bool> BfAddAsync(string key, string item);
		Task<bool[]> BfMAddAsync(string key, string[] items);
		Task<string> BfInsertAsync(string key, string[] items, long? capacity = null, string error = null, int expansion = 2, bool noCreate = false, bool nonScaling = false);
		Task<bool> BfExistsAsync(string key, string item);
		Task<bool[]> BfMExistsAsync(string key, string[] items);
		Task<ScanResult<Byte[]>> BfScanDumpAsync(string key, long iter);
		Task<string> BfLoadChunkAsync(string key, long iter, Byte[] data);
		Task<Dictionary<string, string>> BfInfoAsync(string key);
		Task<string> CmsInitByDimAsync(string key, long width, long depth);
		Task<string> CmsInitByProbAsync(string key, decimal error, decimal probability);
		Task<long> CmsIncrByAsync(string key, string item, long increment);
		Task<long[]> CmsIncrByAsync(string key, Dictionary<string, long> itemIncrements);
		Task<long[]> CmsQueryAsync(string key, string[] items);
		Task<string> CmsMergeAsync(string dest, long numKeys, string[] src, long[] weights);
		Task<Dictionary<string, string>> CmsInfoAsync(string key);
		Task<string> CfReserveAsync(string key, long capacity, long? bucketSize = null, long? maxIterations = null, int? expansion = null);
		Task<bool> CfAddAsync(string key, string item);
		Task<bool> CfAddNxAsync(string key, string item);
		Task<string> CfInsertAsync(string key, string[] items, long? capacity = null, bool noCreate = false);
		Task<string> CfInsertNxAsync(string key, string[] items, long? capacity = null, bool noCreate = false);
		Task<bool> CfExistsAsync(string key, string item);
		Task<bool> CfDelAsync(string key, string item);
		Task<long> CfCountAsync(string key, string item);
		Task<ScanResult<Byte[]>> CfScanDumpAsync(string key, long iter);
		Task<string> CfLoadChunkAsync(string key, long iter, Byte[] data);
		Task<Dictionary<string, string>> CfInfoAsync(string key);
		Task<string> TopkReserveAsync(string key, long topk, long width, long depth, decimal decay);
		Task<string[]> TopkAddAsync(string key, string[] items);
		Task<string> TopkIncrByAsync(string key, string item, long increment);
		Task<string[]> TopkIncrByAsync(string key, Dictionary<string, long> itemIncrements);
		Task<bool[]> TopkQueryAsync(string key, string[] items);
		Task<long[]> TopkCountAsync(string key, string[] items);
		Task<string[]> TopkListAsync(string key);
		Task<Dictionary<string, string>> TopkInfoAsync(string key);
		Task<string> JsonGetAsync(string key, string indent = null, string newline = null, string space = null, params string[] paths);
		Task<string[]> JsonMGetAsync(string[] keys, string path = "$");
		Task JsonSetAsync(string key, string value, string path = "$", bool nx = false, bool xx = false);
		Task JsonMSetAsync(string[] keys, string[] values, string[] paths);
		Task JsonMergeAsync(string key, string path, string value);
		Task<long> JsonDelAsync(string key, string path = "$");
		Task<long[]> JsonArrInsertAsync(string key, string path, long index = 0, params object[] values);
		Task<long[]> JsonArrAppendAsync(string key, string path, params object[] values);
		Task<long[]> JsonArrIndexAsync<T>(string key, string path, T value) where T : struct;
		Task<long[]> JsonArrLenAsync(string key, string path);
		Task<object[]> JsonArrPopAsync(string key, string path, int index = -1);
		Task<long[]> JsonArrTrimAsync(string key, string path, int start, int stop);
		Task<long> JsonClearAsync(string key, string path = "$");
		Task<long[]> JsonDebugMemoryAsync(string key, string path = "$");
		Task<long> JsonForgetAsync(string key, string path = "$");
		Task<string> JsonNumIncrByAsync(string key, string path, double value);
		Task<string> JsonNumMultByAsync(string key, string path, double value);
		Task<string[][]> JsonObjKeysAsync(string key, string path = "$");
		Task<long[]> JsonObjLenAsync(string key, string path = "$");
		Task<object[][]> JsonRespAsync(string key, string path = "$");
		Task<long[]> JsonStrAppendAsync(string key, string value, string path = "$");
		Task<long[]> JsonStrLenAsync(string key, string path = "$");
		Task<bool[]> JsonToggleAsync(string key, string path = "$");
		Task<string[]> JsonTypeAsync(string key, string path = "$");
		Task<long> PublishAsync(string channel, string message);
		Task<long> PublishAsync(string channel, Byte[] message);
		Task<string[]> PubSubChannelsAsync(string pattern = "*");
		Task<long> PubSubNumSubAsync(string channel);
		Task<long[]> PubSubNumSubAsync(string[] channels);
		Task<long> PubSubNumPatAsync();
		IDisposable PSubscribe(string pattern, Action<string, object> handler);
		IDisposable PSubscribe(string[] pattern, Action<string, object> handler);
		IDisposable Subscribe(string[] channels, Action<string, object> handler);
		IDisposable Subscribe(string channel, Action<string, object> handler);
		Task<object> EvalAsync(string script, string[] keys = null, params object[] arguments);
		Task<object> EvalShaAsync(string sha1, string[] keys = null, params object[] arguments);
		Task<bool> ScriptExistsAsync(string sha1);
		Task<bool[]> ScriptExistsAsync(string[] sha1);
		Task ScriptFlushAsync();
		Task ScriptKillAsync();
		Task<string> ScriptLoadAsync(string script);
		object Eval(string script, string[] keys = null, params object[] arguments);
		object EvalSha(string sha1, string[] keys = null, params object[] arguments);
		object SlowLog(string subcommand, params string[] argument);
		Task<long> SAddAsync(string key, params object[] members);
		Task<long> SCardAsync(string key);
		Task<string[]> SDiffAsync(params string[] keys);
		Task<T[]> SDiffAsync<T>(params string[] keys);
		Task<long> SDiffStoreAsync(string destination, params string[] keys);
		Task<string[]> SInterAsync(params string[] keys);
		Task<T[]> SInterAsync<T>(params string[] keys);
		Task<long> SInterStoreAsync(string destination, params string[] keys);
		Task<bool> SIsMemberAsync<T>(string key, T member);
		Task<string[]> SMembersAsync(string key);
		Task<T[]> SMembersAsync<T>(string key);
		Task<bool[]> SMIsMemberAsync(string key, params object[] members);
		Task<bool> SMoveAsync<T>(string source, string destination, T member);
		Task<string> SPopAsync(string key);
		Task<T> SPopAsync<T>(string key);
		Task<string[]> SPopAsync(string key, int count);
		Task<T[]> SPopAsync<T>(string key, int count);
		Task<string> SRandMemberAsync(string key);
		Task<T> SRandMemberAsync<T>(string key);
		Task<string[]> SRandMemberAsync(string key, int count);
		Task<T[]> SRandMemberAsync<T>(string key, int count);
		Task<long> SRemAsync(string key, params object[] members);
		Task<ScanResult<string>> SScanAsync(string key, long cursor, string pattern, long count);
		Task<ScanResult<T>> SScanAsync<T>(string key, long cursor, string pattern, long count);
		Task<string[]> SUnionAsync(params string[] keys);
		Task<T[]> SUnionAsync<T>(params string[] keys);
		Task<long> SUnionStoreAsync(string destination, params string[] keys);
		Task<ZMember> BZPopMinAsync(string key, int timeoutSeconds);
		Task<KeyValue<ZMember>> BZPopMinAsync(string[] keys, int timeoutSeconds);
		Task<ZMember> BZPopMaxAsync(string key, int timeoutSeconds);
		Task<KeyValue<ZMember>> BZPopMaxAsync(string[] keys, int timeoutSeconds);
		Task<long> ZAddAsync(string key, decimal score, string member, params object[] scoreMembers);
		Task<long> ZAddAsync(string key, ZMember[] scoreMembers, ZAddThan? than = null, bool ch = false);
		Task<long> ZAddNxAsync(string key, decimal score, string member, params object[] scoreMembers);
		Task<long> ZAddNxAsync(string key, ZMember[] scoreMembers, ZAddThan? than = null, bool ch = false);
		Task<long> ZAddXxAsync(string key, decimal score, string member, params object[] scoreMembers);
		Task<long> ZAddXxAsync(string key, ZMember[] scoreMembers, ZAddThan? than = null, bool ch = false);
		Task<long> ZCardAsync(string key);
		Task<long> ZCountAsync(string key, decimal min, decimal max);
		Task<long> ZCountAsync(string key, string min, string max);
		Task<decimal> ZIncrByAsync(string key, decimal increment, string member);
		Task<long> ZInterStoreAsync(string destination, string[] keys, int[] weights = null, ZAggregate? aggregate = null);
		Task<long> ZLexCountAsync(string key, string min, string max);
		Task<ZMember> ZPopMinAsync(string key);
		Task<ZMember[]> ZPopMinAsync(string key, int count);
		Task<ZMember> ZPopMaxAsync(string key);
		Task<ZMember[]> ZPopMaxAsync(string key, int count);
		Task<string[]> ZRangeAsync(string key, decimal start, decimal stop);
		Task<ZMember[]> ZRangeWithScoresAsync(string key, decimal start, decimal stop);
		Task<string[]> ZRangeByLexAsync(string key, string min, string max, int offset = 0, int count = 0);
		Task<string[]> ZRangeByScoreAsync(string key, decimal min, decimal max, int offset = 0, int count = 0);
		Task<string[]> ZRangeByScoreAsync(string key, string min, string max, int offset = 0, int count = 0);
		Task<ZMember[]> ZRangeByScoreWithScoresAsync(string key, decimal min, decimal max, int offset = 0, int count = 0);
		Task<ZMember[]> ZRangeByScoreWithScoresAsync(string key, string min, string max, int offset = 0, int count = 0);
		Task<long?> ZRankAsync(string key, string member);
		Task<long> ZRemAsync(string key, params string[] members);
		Task<long> ZRemRangeByLexAsync(string key, string min, string max);
		Task<long> ZRemRangeByRankAsync(string key, long start, long stop);
		Task<long> ZRemRangeByScoreAsync(string key, decimal min, decimal max);
		Task<long> ZRemRangeByScoreAsync(string key, string min, string max);
		Task<string[]> ZRevRangeAsync(string key, decimal start, decimal stop);
		Task<ZMember[]> ZRevRangeWithScoresAsync(string key, decimal start, decimal stop);
		Task<string[]> ZRevRangeByLexAsync(string key, decimal max, decimal min, int offset = 0, int count = 0);
		Task<string[]> ZRevRangeByLexAsync(string key, string max, string min, int offset = 0, int count = 0);
		Task<string[]> ZRevRangeByScoreAsync(string key, decimal max, decimal min, int offset = 0, int count = 0);
		Task<string[]> ZRevRangeByScoreAsync(string key, string max, string min, int offset = 0, int count = 0);
		Task<ZMember[]> ZRevRangeByScoreWithScoresAsync(string key, decimal max, decimal min, int offset = 0, int count = 0);
		Task<ZMember[]> ZRevRangeByScoreWithScoresAsync(string key, string max, string min, int offset = 0, int count = 0);
		Task<long> ZRevRankAsync(string key, string member);
		Task<decimal?> ZScoreAsync(string key, string member);
		Task<long> ZUnionStoreAsync(string destination, string[] keys, int[] weights = null, ZAggregate? aggregate = null);
		Task<long> XAckAsync(string key, string group, params string[] id);
		Task<string> XAddAsync<T>(string key, string field, T value, params object[] fieldValues);
		Task<string> XAddAsync<T>(string key, long maxlen, string id, string field, T value, params object[] fieldValues);
		Task<string> XAddAsync<T>(string key, Dictionary<string, T> fieldValues);
		Task<string> XAddAsync<T>(string key, long maxlen, string id, Dictionary<string, T> fieldValues);
		Task<StreamsXAutoClaimResult> XAutoClaimAsync(string key, string group, string consumer, long minIdleTime, string start, long count = 0);
		Task<StreamsEntry[]> XClaimAsync(string key, string group, string consumer, long minIdleTime, params string[] id);
		Task<StreamsEntry[]> XClaimAsync(string key, string group, string consumer, long minIdleTime, string[] id, long idle, long retryCount, bool force);
		Task<string[]> XClaimJustIdAsync(string key, string group, string consumer, long minIdleTime, params string[] id);
		Task<string[]> XClaimJustIdAsync(string key, string group, string consumer, long minIdleTime, string[] id, long idle, long retryCount, bool force);
		Task<long> XDelAsync(string key, params string[] id);
		Task XGroupCreateAsync(string key, string group, string id = "$", bool MkStream = false);
		Task XGroupSetIdAsync(string key, string group, string id = "$");
		Task<bool> XGroupDestroyAsync(string key, string group);
		Task XGroupCreateConsumerAsync(string key, string group, string consumer);
		Task<long> XGroupDelConsumerAsync(string key, string group, string consumer);
		Task<StreamsXInfoStreamResult> XInfoStreamAsync(string key);
		Task<StreamsXInfoStreamFullResult> XInfoStreamFullAsync(string key, long count = 10);
		Task<StreamsXInfoGroupsResult[]> XInfoGroupsAsync(string key);
		Task<StreamsXInfoConsumersResult[]> XInfoConsumersAsync(string key, string group);
		Task<long> XLenAsync(string key);
		Task<StreamsXPendingResult> XPendingAsync(string key, string group);
		Task<StreamsXPendingConsumerResult[]> XPendingAsync(string key, string group, string start, string end, long count, string consumer = null);
		Task<StreamsEntry[]> XRangeAsync(string key, string start, string end, long count = -1);
		Task<StreamsEntry[]> XRevRangeAsync(string key, string end, string start, long count = -1);
		Task<StreamsEntry> XReadAsync(long block, string key, string id);
		Task<StreamsEntryResult[]> XReadAsync(long count, long block, string key, string id, params string[] keyIds);
		Task<StreamsEntryResult[]> XReadAsync(long count, long block, Dictionary<string, string> keyIds);
		Task<StreamsEntry> XReadGroupAsync(string group, string consumer, long block, string key, string id);
		Task<StreamsEntryResult[]> XReadGroupAsync(string group, string consumer, long count, long block, bool noack, string key, string id, params string[] keyIds);
		Task<StreamsEntryResult[]> XReadGroupAsync(string group, string consumer, long count, long block, bool noack, Dictionary<string, string> keyIds);
		Task<long> XTrimAsync(string key, long count);
		Task<long> AppendAsync<T>(string key, T value);
		Task<long> BitCountAsync(string key, long start, long end);
		Task<long[]> BitFieldAsync(string key, params BitFieldAction[] actions);
        Task<long> BitOpAsync(BitOpOperation operation, string destkey, params string[] keys);
		Task<long> BitPosAsync(string key, bool bit, long? start = null, long? end = null);
		Task<long> DecrAsync(string key);
		Task<long> DecrByAsync(string key, long decrement);
		Task<string> GetAsync(string key);
		Task<T> GetAsync<T>(string key);
		Task GetAsync(string key, Stream destination, int bufferSize = 1024);
		Task<bool> GetBitAsync(string key, long offset);
		Task<string> GetRangeAsync(string key, long start, long end);
		Task<T> GetRangeAsync<T>(string key, long start, long end);
		Task<string> GetSetAsync<T>(string key, T value);
		Task<long> IncrAsync(string key);
		Task<long> IncrByAsync(string key, long increment);
		Task<decimal> IncrByFloatAsync(string key, decimal increment);
		Task<string[]> MGetAsync(params string[] keys);
		Task<T[]> MGetAsync<T>(params string[] keys);
		Task MSetAsync(string key, object value, params object[] keyValues);
		Task MSetAsync<T>(Dictionary<string, T> keyValues);
		Task<bool> MSetNxAsync(string key, object value, params object[] keyValues);
		Task<bool> MSetNxAsync<T>(Dictionary<string, T> keyValues);
		Task PSetExAsync<T>(string key, long milliseconds, T value);
		Task SetAsync<T>(string key, T value, int timeoutSeconds = 0);
		Task SetAsync<T>(string key, T value, bool keepTtl);
		Task<bool> SetNxAsync<T>(string key, T value, int timeoutSeconds);
		Task<bool> SetNxAsync<T>(string key, T value, TimeSpan timeout);
		Task<bool> SetXxAsync<T>(string key, T value, int timeoutSeconds = 0);
		Task<bool> SetXxAsync<T>(string key, T value, TimeSpan timeout);
		Task<bool> SetXxAsync<T>(string key, T value, bool keepTtl);
		Task<string> SetAsync<T>(string key, T value, TimeSpan timeout, bool keepTtl, bool nx, bool xx, bool get);
		Task SetAsync<T>(string key, T value, TimeSpan timeout);
		Task<long> SetBitAsync(string key, long offset, bool value);
		Task SetExAsync<T>(string key, int seconds, T value);
		Task<bool> SetNxAsync<T>(string key, T value);
		Task<long> SetRangeAsync<T>(string key, long offset, T value);
		Task<long> StrLenAsync(string key);
#endif
	}
}